package br3akr.DeadlyDinnerParty.Server.Actions;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;

import br3akr.DeadlyDinnerParty.Server.Engine.Server;
import br3akr.DeadlyDinnerParty.Server.Engine.Session;
import br3akr.DeadlyDinnerParty.Server.Exceptions.DeadlyDinnerPartyException;
import br3akr.DeadlyDinnerParty.Server.World.Area;
import br3akr.DeadlyDinnerParty.Server.World.Exit;
import br3akr.DeadlyDinnerParty.Server.World.GameCharacter;
import br3akr.DeadlyDinnerParty.Server.World.Exit.ExitStatus;

public class BashAction extends Action {
    private ActionResponse actionResponse;
    public static final Set<String> keywords;
	static
	{
		Set<String>tempKeywords = new HashSet<String>();
		tempKeywords.add("Bash");
		tempKeywords.add("Ba");
		keywords = Collections.unmodifiableSet(tempKeywords);
	}
    
    public BashAction() {
        super("Bash", false);
    }
    
    public ActionResponse doAction(String action, Session session) throws DeadlyDinnerPartyException {
		if (action == null) {
			throw new DeadlyDinnerPartyException ("No action found.");
		}
		if (session == null) {
			throw new DeadlyDinnerPartyException ("No session found.");
		}
		
    	StringTokenizer tokenizedAction = new StringTokenizer(action);
    	tokenizedAction.nextToken(); // Ignore the keyword 'bash'
    	String param1 = null;
    	
    	if (tokenizedAction.hasMoreTokens()) {
    		param1 = tokenizedAction.nextToken();
    	}
    	
		if (param1 == null) {
			throw new DeadlyDinnerPartyException ("What do you want to smash open?");
		}
    	
		GameCharacter actor = session.getCharacter();
		
		if (actor == null) {
			throw new DeadlyDinnerPartyException ("No character found for your session.");
		}
		
		if (actor.isRecovering()) {
			throw new DeadlyDinnerPartyException ("You can not bash while recovering.");
		}
		
		if (actor.getStatus() == GameCharacter.Status.INCAPACITATED) {
			throw new DeadlyDinnerPartyException ("You can not bash while incapacitated.");
		}
		
    	actionResponse = new ActionResponse();
    	actionResponse.setActingCharacter(actor);
    	Area location = session.getCharacter().getLocation();
    	
		Exit exit = location.getExit(Exit.getDirection(param1));
		
		if (exit == null) {
			throw new DeadlyDinnerPartyException ("'" + param1 + " is not a valid exit.");
		}
		
		Exit.ExitStatus curExitStatus = exit.getStatus();
		
		if (curExitStatus == ExitStatus.OPEN) {
			throw new DeadlyDinnerPartyException("The door to the " + exit.getExitDirection(location) + " is already opened.");
		}
		if (curExitStatus == ExitStatus.BASHED) {
			throw new DeadlyDinnerPartyException("The door to the " + exit.getExitDirection(location) + " has already been bashed open.");
		}
    	
    	Area exitLocation = exit.getExitArea(location);
    	
		Set<GameCharacter> onlookers;
		
		for (Area curArea : Server.world.getAreas()) {
			onlookers = curArea.getAreaOnlookers(session.getCharacter(), null);
			actionResponse.addAffectedArea(curArea);
			actionResponse.addOnlookers(onlookers, "You hear a thunderous smashing coming from " + location.getName() + "!");
		}
		
    	Set<GameCharacter> localOnlookers = location.getAreaOnlookers(session.getCharacter(), null);
    	Set<GameCharacter> exitOnlookers = exitLocation.getAreaOnlookers(session.getCharacter(), null);
    	actionResponse.addAffectedArea(location);
    	actionResponse.addAffectedArea(exitLocation);
		exit.setStatus(ExitStatus.BASHED);
		actionResponse.addOnlookers(localOnlookers, session.getCharacter().getName() + " smashes down the door to " + exitLocation.getName() + " in the " + exit.getExitDirection(location) + "!");
		actionResponse.addOnlookers(exitOnlookers, "The door to " + location.getName() + " in the " + exit.getExitDirection(location) + " cracks off its hinges and crashes to the floor as someone smashes it open!");
		actionResponse.setActingCharacterDescription("You smash down the door to " + exitLocation.getName() + " - " + exit + "!");
		beginRecovery(session.getCharacter(), 3000);
		
        return actionResponse;
    }
	
    public ActionResponse getActionResponse() {
		return actionResponse;
	}
    
    public Set<String> getKeywords() {
        return keywords;
    }
}